56장. S3 — 객체 스토리지의 기본
이 장에서 말하고자 하는 것
앞 장에서 객체 스토리지의 개념을 봤다.
이제 그 대표 주자
Amazon S3 (Simple Storage Service)
를 본다.
S3는 AWS에서 가장 오래된 서비스이자 가장 많이 쓰이는 서비스다.
1. 기본 단위 — 버킷과 객체
버킷 "msa-uploads"
├─ users/123/profile.png
├─ orders/2025/01/15/order-123.json
└─ static/app.a3f2c.js
- 버킷(Bucket) : 글로벌 고유한 이름의 컨테이너
- 객체(Object) : 키(경로) + 값(데이터) + 메타데이터
폴더는 사실 가짜다 — users/123/profile.png 는 한 객체의 키 문자열.
2. 버킷 이름은 글로벌
S3 버킷 이름은 전 세계에서 유일 해야 한다.
이미 누가 쓰는 이름 → 만들 수 없다
운영에서는 회사/조직 식별자 + 환경 + 용도 패턴을 쓴다.
acme-prod-uploads
acme-prod-logs
acme-dev-static
3. S3는 사실상 무제한
- 객체 크기 최대 5TB
- 버킷당 객체 수 제한 없음
- 처리량 자동 확장
용량 걱정 없이 쓴다는 게 S3의 첫 번째 장점
4. 강한 일관성
2020년부터 S3는 read-after-write consistency 가 기본이다.
PUT 직후 GET → 방금 쓴 내용을 반드시 받는다
옛날에는 결국 일관성(eventual)이었지만 지금은 아니다.
5. 권한 — Public이 아니다, 항상
S3 버킷은 기본적으로 비공개다.
Public Access Block ON ← 항상 켠다
권한은 두 방식으로 준다.
- IAM 정책 — 누가(주체) 무엇을 할 수 있는가
- 버킷 정책 — 이 버킷에 누가 접근할 수 있는가
6. 사전 서명 URL — 임시 권한
직접 노출하지 않고 객체에 일시 접근을 주는 방식이다.
서버 → 사용자에게 "5분 동안 유효한 URL" 전달
사용자 → 그 URL로 직접 S3 GET/PUT
다음 58장에서 자세히 본다.
7. CloudFront와 함께 — 정적 호스팅 표준
S3 (비공개, OAC)
↑
CloudFront (HTTPS, 캐시)
↑
사용자
이게 정적 자원의 표준 모양이다 (39장).
8. 우리 서비스에서
[S3 버킷들]
├─ static → SPA 빌드 결과 (CloudFront 노출)
├─ uploads → 사용자 업로드 (사전 서명 URL)
├─ ecs-logs → ECS 로그 백업
└─ data-archive → 분석용 백업
용도별로 버킷을 분리한다.
- 권한이 다르다
- 수명 주기가 다르다
- 비용 분석이 쉬워진다
9. 직접 확인해보기 — CLI
aws s3 mb s3://msa-uploads
aws s3 cp ./profile.png s3://msa-uploads/users/123/profile.png
aws s3 cp s3://msa-uploads/users/123/profile.png ./
aws s3 ls s3://msa-uploads/users/123/
aws s3 sync ./build s3://msa-static/
s3 sync 는 정적 배포에 가장 자주 쓴다.
10. 코드로는 이렇게 생겼다 — Terraform
resource "aws_s3_bucket" "uploads" {
bucket = "msa-prod-uploads"
}
resource "aws_s3_bucket_public_access_block" "uploads" {
bucket = aws_s3_bucket.uploads.id
block_public_acls = true
block_public_policy = true
ignore_public_acls = true
restrict_public_buckets = true
}
resource "aws_s3_bucket_versioning" "uploads" {
bucket = aws_s3_bucket.uploads.id
versioning_configuration {
status = "Enabled"
}
}
resource "aws_s3_bucket_server_side_encryption_configuration" "uploads" {
bucket = aws_s3_bucket.uploads.id
rule {
apply_server_side_encryption_by_default {
sse_algorithm = "AES256"
}
}
}
네 가지 (생성 + Public 차단 + 버전 + 암호화) 가 운영 출발선이다.
11. 이렇게 쓰면 망한다 — 안티패턴
안티패턴 1. Public Access Block을 끈다
대부분의 S3 노출 사고가 여기서 시작된다.
항상 켠다. 공개가 필요하면 CloudFront + OAC로
안티패턴 2. 같은 버킷에 모든 걸 섞는다
권한 · 수명 · 비용이 다 섞인다.
용도별 버킷 분리
안티패턴 3. versioning을 안 켠다
실수로 덮어쓰면 복구가 안 된다.
안티패턴 4. 사용자 업로드에 원본 파일명을 그대로 쓴다
충돌 · 인젝션 위험.
UUID / hash 로 키를 생성한다
12. 한 줄로 정리
S3는 글로벌 단위의 버킷 안에 객체를 HTTP API로 다루는 무제한 저장소다
13. 이 장의 핵심 정리
- S3의 단위는 버킷(글로벌 고유) + 객체(키 + 값) 다.
- 폴더는 가짜다. 키 문자열일 뿐.
- 2020년 이후 강한 일관성을 보장한다.
- Public Access Block은 항상 켜고, 공개는 CloudFront + OAC로.
- 운영 출발선: 버킷 + Public 차단 + 버전 + 암호화.
- 용도별 버킷을 분리한다.